#include <stdio.h>

/* 信号量相关开关*/
#define __SEM__           0

/* 必要基础定义*/
typedef short             i16;
typedef unsigned short    u16;
typedef unsigned long     u64;    

short coroutine_count = 0;              /* 协程数量*/
static u64 system_tick = 0;             /* 系统时间*/

/* 协程状态定义*/
#define CT_FLAG_EMPTY    -1
#define CT_FLAG_PREPARE   0x01
#define CT_FLAG_RUNNING   0x02
#define CT_FLAG_SUSPEND   0x04
#define CT_FLAG_END       0x08

/* 协程注册状态定义*/
#define CT_REGISTER_OK    1
#define CT_REGISTER_ERROR 0

/* 协程结构体*/
typedef struct{
    i16 state;                        /* 协程状态*/
    u16 context;                      /* 协程上下文*/
    u64 wake_tick;                    /* 唤醒时间戳*/
    i16 (*func)(i16);                 /* 协程函数*/
}coroutine_t;

/* 协程结构*/
#define CT_BEGIN()    do{                                                 \
    if((register_table[id]).state == CT_FLAG_PREPARE) {                   \
        (register_table[id]).state = CT_FLAG_RUNNING;                     \
    }                                                                     \
    switch((register_table[id]).context) {                                \
        case 0:;

#define CT_SUSPEND()  do{                                                 \
    (register_table[id]).context = __LINE__;                              \
    (register_table[id]).state = CT_FLAG_SUSPEND;                         \
    return CT_FLAG_SUSPEND;                                               \
    case __LINE__: ;                                                      \
}while(0)

#define CT_END()      }                                                   \
    (register_table[id]).state = CT_FLAG_END;                             \
    return CT_FLAG_END;                                                   \
}while(0)           

/* 协程注册表*/
coroutine_t register_table[10]=
{   
    {CT_FLAG_EMPTY,0,0,NULL},
    {CT_FLAG_EMPTY,0,0,NULL},
    {CT_FLAG_EMPTY,0,0,NULL},
    {CT_FLAG_EMPTY,0,0,NULL},
    {CT_FLAG_EMPTY,0,0,NULL},
    {CT_FLAG_EMPTY,0,0,NULL},
    {CT_FLAG_EMPTY,0,0,NULL},
    {CT_FLAG_EMPTY,0,0,NULL},
    {CT_FLAG_EMPTY,0,0,NULL},
    {CT_FLAG_EMPTY,0,0,NULL}
};

/* 协程注册*/
short coroutine_register(coroutine_t *ct,i16 (*func)(i16))
{
    if(coroutine_count >= 10){
        printf("ERROR!,the coroutine count is too much\n");
        return CT_REGISTER_ERROR;
    }

    register_table[coroutine_count] = *ct;
    register_table[coroutine_count].func = func;
    register_table[coroutine_count].context = 0;
    register_table[coroutine_count].state = CT_FLAG_PREPARE;

    coroutine_count++;
    return CT_REGISTER_OK;
}

#if __SEM__

    /* 信号量状态定义*/
    #define SEM_FLAG_WAIT_FOREVER   0x10
    #define SEM_FLAG_WAIT_LOCK      0x20

    /* 信号量结构体*/
    typedef struct{
        i16 wait_list[10];            /* 等待队列*/
        u16 wait_count;               /* 等待数量*/
    }ct_sem_t;

    /* 信号量结构宏*/
    #define CT_WAIT_SEM(sem)  do{                                            \
        if(sem_try_take(sem)) {                                              \
            break;                                                           \
        }                                                                    \
        register_table[id].context = __LINE__;                               \
        register_table[id].state |= SEM_FLAG_WAIT_FOREVER;                   \
        printf("state 0x%x\n",register_table[id].state);                     \
        return register_table[id].state;                                     \
        case __LINE__: ;                                                     \
    }while(0)

    /* 信号量初始化*/
    void sem_init(ct_sem_t *sem, u16 count)
    {
        sem->wait_count = count;
    }

    /* 获取信号量*/
    i16 sem_try_take(ct_sem_t *sem)
    {
        if(sem->wait_count > 0){
            for(u16 i=1; i<sem->wait_count; i++){
                /* 队列集体前进一步*/
                sem->wait_list[i-1] = sem->wait_list[i];
            }

            /* 信号量减一*/
            sem->wait_count--;
            
            printf("sem take successed\n");
            return 1;
        }
        else{
        //    printf("sem take failed\n");
        }
        return 0;
    }

    /* 发送信号量到管道队列*/
    void sem_sent(ct_sem_t *sem, i16 id)
    {
        if(sem->wait_count < 10){
            printf("sent sem successed\n");
            sem->wait_list[sem->wait_count++] = id;

            /* 唤醒第一个等待的协程*/
            if(register_table[id].state & SEM_FLAG_WAIT_FOREVER) {
                register_table[id].state = CT_FLAG_PREPARE;
            }
        }
        else{
        //    printf("ERROR!,the semaphore is full\n");
        }
    }

#endif


/*　协程调度器*/
void scheduler(void)
{
    i16 i;
    while(1){

        for(i=0;i<coroutine_count;i++){
            if(register_table[i].state == CT_FLAG_PREPARE || 
               register_table[i].state == CT_FLAG_SUSPEND){
                i16 result = register_table[i].func(i);
                register_table[i].state = result;
            }
        }
    }
}